/*
**  File MultiPlot.c
*/
#include <limits.h>
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

/* BEGIN_EXTH */
#include "MultiPlotTypes.h"
/* END_EXTH */


#ifdef MYDATAisDOUBLE
#define    MYDATA_MIN  (-(DBL_MAX))
#define    MYDATA_MAX  (DBL_MAX)
#define    PREP_FMT    "%.0lg"
#define    XFMT        "%%-%i.3lg"
#define    YFMT        "%%%i.2lg"
#define    XADDLEN     2
#define    YADDLEN     2
#endif

#ifdef MYDATAisFLOAT
#define    MYDATA_MIN  (-(FLT_MAX))
#define    MYDATA_MAX  (FLT_MAX)
#define    PREP_FMT    "%.0g"
#define    XFMT        "%%-%i.3g"
#define    YFMT        "%%%i.2g"
#define    XADDLEN     2
#define    YADDLEN     2
#endif

#ifdef MYDATAisINT
#define    MYDATA_MIN  (INT_MIN)
#define    MYDATA_MAX  (INT_MAX)
#define    PREP_FMT    "%i"
#define    XFMT        "%%-%ii"
#define    YFMT        "%%%ii"
#define    XADDLEN     0
#define    YADDLEN     0
#endif

#ifdef MYDATAisLONG
#define    MYDATA_MIN  (LONG_MIN)
#define    MYDATA_MAX  (LONG_MAX)
#define    PREP_FMT    "%li"
#define    XFMT        "%%-%ili"
#define    YFMT        "%%%ili"
#define    XADDLEN     0
#define    YADDLEN     0
#endif

#define    kFontWidth   6      /* for calculation of label size 
                                  (should be the same as in MultiPlot_mac.c) */

#define    spc        0.05     /* spacing between plots (fraction of plotsize) */
#define    marg       5        /* spacing from window boundary (pixels) */

#ifdef UNIX_CC
#define CONSOLE                /* this is just to avoid the call to GetKey */
#endif

#ifdef CONSOLE
#define    kStsHeight 10        /* height of status line */
#else
#define    kStsHeight  0        /* height of status line */
#endif


/*****************/
/*  Functions    */
/*****************/

#include "General.h"
#include "Functs.h"
#include "MultiPlot.h"

static void PrepData( MyDataset *DD, MyDatasize *DDsize );
static void PrepPlot( MyDatarecPtr xdata, MyDatarecPtr ydata, MyDatasize *DDsize );
static void PrepPage( Rect *canvas, int nx, int ny, int *dx, int *dy, 
                      int *xsz, int *ysz, MyDataset *DD, MyDatasize *DDsize );

#ifdef UNIX_CC
static void  GraphPageInit( char *text ); 
static void  GraphPageEnd( void );
#endif
#ifdef MAC_THINK_C
#include "MultiPlot_mac.h"
#endif

/*************/
/*  Globals  */
/*************/

FILE       *fpg;           /* the console file associated with the graphics window */
                           /* used ifdef CONSOLE; otherwise use graphics 
                              window not associated with console */
WindowPtr  window;         /* the graphics window */

char       xfmt[20];       /* format string for labels on x-axis */
char       yfmt[20];       /* format string for labels on y-axis */
int        xlab = 10;      /* pixels in y direction for x-axis labels */
int        ylab = 20;      /* pixels in x direction for y-axis labels */
int        ntic = 5;       /* number of tic mark intervals */

Boolean    graph_on = false;



/* BEGIN_EXTH */


/**************** MultiPlot ****************/

/*
**  Plot one or more series of data points.
**  The data are supposed to be stored in equidimensional records.
**  The present implementation (MultiPlot, PrepData) assumes that the first
**  record is used for the x-data of all plots.
**
**  First PrepData is called to prepare the data. Then the plot page is
**  initialized by GraphPageInit, and plot parameters are set by PrepPage.
**  Data are plotted by repeated calls to PlotData.
**  A loop may be formed from: 
**     GraphPageInit, PrepPage, repeat( PrepPlot-optional, PlotData), GraphPageEnd.
**
**  The system dependent routines are GraphPageInit, GraphPageEnd, PlotData
**  and GetKey1/2.
**
**  The 'page' can contain multiple plots. The number of plots (nx, ny)
**  has to be passed to PrepPage. The minimum and maximum data values to be
**  plotted are stored in DDsize. If both minimum and maximum are 0 PrepData
**  takes care that all records in the data set will fit, and will
**  be plotted using the same values. (It takes the values from DD itself,
**  and they are set in PrepData assuming that the first record is always x!!).
**  If <global> has been set the global scaling is overruled by calls to PrepPlot, which takes
**  the minimum and maximum values from the x,y pair to be plotted.
**
**  Other values may be set in DDsize by the user (**to be coded**).
**  A 'neat' option has **to be implemented** in PrepData/PrepPlot (divide del iteratively
**  by 10, or multiply by 10, until value inside { 1, 2, 5, 25 }; try
**  different values of ntic, e.g. 4, 5, 6, and choose the one giving the
**  smallest difference between the data max. and the axis max.)
**
**  Arguments:
**
**  DD: pointer to the data set (all data must have been set, except the
**      minimum and maximum values)
**  text: string used as first part of window title (will be supplemented
**      with some info)
**  nx: number of plots in x direction (may be 0)
**  ny: number of plots in y direction (may be 0)
**  indyp: array of indices of records to be plotted as y-values (may be NULL)
**         NOTE: index 1 is mapped on record[1], 
**         i.e. the first record after the x-data record !
**         If the index is outside the allowed range the plot is skipped.
**         If indyp is used, the number of elements in the array should not be
**         less than nx*ny.
**  (replace i[nd]yp by string of symbols, indicating indices and plot options
**   such as switch to histogram, overlay plot etc. )
**  global: if true, all plots are scaled in the same way
**  more: if true, more plots than nx*ny are available
**
**  Returns <true> if final status is "quit".
*/

#define size_CMM  2000

Boolean	MultiPlot( MyDataset *DD, char *text, int *IDnum, int nx, int ny, 
                   int *indyp, const Boolean global, const Boolean more )
{    
    MyDatasize DDsize = { 0, 0, 0, 0 };
    Rect       canvas;            /* rectangle enclosing all plots */
    int        dx, dy;            /* pixel shift between plots (incl. label and margin) */
    int        xsz, ysz;          /* pixel plot size (excl. labels and margins) */
    int        xminscreen;        /* pixel left side of plot (excl. label) */
    int        yminscreen;        /* pixel top side of plot (excl. label) */
    int        c, i, j, k;
    int        grph, *iyp = indyp, *iyp_alloc = NULL;
    Boolean    quit = false;
    char       wtitle[200], nam[10];
#ifdef UNIX_CC
    FILE       *fp;
    char       str[200], stp[200], cmm[size_CMM];
    char       *params = "xmgr.par";
    char       *pltcmm  = "/usr/ruuci11/people/ruu/bin/xmgr";
    char       *pltcmm2 = " &";
/*
    char       *pltcmm2 = " -p xmgr.par &";
*/
#endif

    printf( "\n-Begin of Multiplot-\n" );

/* is there something to work on? */

    if ( DD->rec_count < 2 )
    {
        printf( "Only %i data records available\n", DD->rec_count );
        exit( 1 );
    }
    if ( DD->data_count < 2 )
    {
        printf( "Only %i data points available\n", DD->data_count );
        exit( 1 );
    }

/* prepare the data */

    PrepData( DD, &DDsize );
    
next:

/* ask the user which records to plot - assume that first record is x!! (cf. PrepData) */

    printf( "%i data points in %i data records - first record taken as x\n", 
            DD->data_count, DD->rec_count );
    if ( nx == 0 || ny == 0 )
    {
        printf( "Give number of plots in x, y direction: " );
        scanf( "%i %i", &nx, &ny );
        iyp = NULL;
    }
    if ( !iyp )
    {
        iyp_alloc = (int *)calloc( nx*ny, sizeof( int ) );
        iyp = iyp_alloc;
        i = 0;
        printf( "Give indices of %i records to plot as y: ", nx*ny );

/* NOTE: index 1 is mapped on record[1], 
  i.e. the first record after the x-data record ! */

        while ( i++ < nx*ny )
            scanf( "%i", iyp++ );
    }

/* form the title for the graphics page */

    if ( !iyp_alloc )
        iyp = indyp;
    else
        iyp = iyp_alloc;
    i = 0;
    strcpy( wtitle, text );
    sprintf( nam, " <%i>", *IDnum );
    strcat( wtitle, nam );
    *IDnum += 1;
    while ( i++ < nx*ny )
    {
        if ( *iyp >= 1 && *iyp <= DD->rec_count-1 )
        {
            sprintf( nam, " %i", *iyp );
            strcat( wtitle, nam );
        }
        iyp++;
    }

/* initialize the graphics page */

    GraphPageInit( wtitle );

/* prepare for plotting */

    canvas = window->portRect;
    canvas.top += marg;
    canvas.bottom -= marg + kStsHeight;
    canvas.left += marg;
    canvas.right -= marg;

    PrepPage( &canvas, nx, ny, &dx, &dy, &xsz, &ysz, DD, &DDsize );

#ifdef DEBUG
    FrameRect( &canvas );
#endif


/* now plot the data */

#ifdef UNIX_CC
    strcpy( cmm, pltcmm );
    sprintf( str, " -arrange %i %i", nx, ny );
    strcat( cmm, str );
/*
    if ( !( fp = fopen( params, "w" ) ) )
    {
        printf( "can't open output file %s\n", params );
        goto end;
    }
*/
#endif
    if ( !iyp_alloc )
        iyp = indyp;
    else
        iyp = iyp_alloc;
    xminscreen = marg + ylab;
    yminscreen = marg;
    grph = 0;
    j = 0;
    while ( j++ < ny )
    {
        i = 0;
        while ( i < nx )
        {
            if ( *iyp >= 1 && *iyp <= DD->rec_count-1 )
	        {
	        	if ( !global )
	        		PrepPlot( &DD->datarec[0], &DD->datarec[*iyp], &DDsize );
#ifdef MAC_THINK_C
                PlotData( &DD->datarec[0], &DD->datarec[*iyp], DD->data_count, &DDsize,
                          xminscreen, xminscreen+xsz, yminscreen, yminscreen+ysz );
#endif
#ifdef UNIX_CC
                sprintf( stp, "-pexec \"xaxis ticklabel char size 0.7\" -pexec \"yaxis ticklabel char size 0.7\" -pexec \"xaxis ticklabel op top\"" );
                sprintf( str, " -graph %i %s %s", grph, stp, DD->datarec[*iyp].fil );
/*
                fprintf( fp, "with g%i\n", grph );
                fprintf( fp, "xaxis ticklabel char size 0.7\nyaxis ticklabel char size 0.7\n" );
                fprintf( fp, "g%i autoscale type AUTO\n", grph );
*/
                if ( strlen( cmm ) + strlen( str ) > size_CMM )
                {
                    puts( "MultiPlot: size_CMM too small" );
                    goto end;
                }
                strcat( cmm, str );
#endif
            }
            iyp++;
            xminscreen += dx;
	        i++;
	        grph++;
        }
        xminscreen = marg + ylab;
        yminscreen += dy;
    }
#ifdef UNIX_CC
/*
    fclose( fp );
*/
    if ( strlen( cmm ) + strlen( pltcmm2 ) > size_CMM )
    {
        puts( "MultiPlot: size_CMM too small" );
        goto end;
    }
    strcat( cmm, pltcmm2 );
    puts( cmm );
    system( cmm );
#endif


/* what next? read character */

#ifdef UNIX_CC
    if ( !more )
        goto end;
    printf( "\ntype n/m/r/e/q:\n\n" );
#endif

what:

#ifdef CONSOLE
    if ( graph_on )
        c = fgetc( fpg );
    else
    {
        c = getchar();
        FlushLine( stdin );
    }
#else
    if ( graph_on )
        while ( !GetKey2( &c ) )
            ;
    else
    {
        c = getchar();
        FlushLine( stdin );
    }
#endif

/* and now close the graphics page */

    GraphPageEnd();

    switch ( c )
    {
        case 'n':        /* next */

			if ( !more )
			{
				quit = false;
				break;
			}
            if ( iyp_alloc )
            {
                free( iyp );
                iyp = NULL;
            }
            else
                indyp += nx*ny;
            iyp = indyp;
            goto next;
            break;

        case 'm':        /* more */

            if ( iyp_alloc )
                free( iyp );
            iyp = NULL;
            goto next;
            break;

        case 'r':        /* reset */

            if ( iyp_alloc )
                free( iyp );
            iyp = NULL;
            nx = 0;
            ny = 0;
            goto next;
            break;

        case 'e':        /* end */

            quit = false;
            break;

        case 'q':        /* quit */

            quit = true;
            break;

        default:

            printf( "type n/m/r/e/q:\n" );
            goto what;

    }

end:

/* end of routine */

    printf( "\n-End of Multiplot-\n" );

#ifdef DEBUG
#ifdef MYDATAisDOUBLE
    printf( "DD min etc.: %lg %lg %lg %lg\n", DD->xmin, DD->xmax, DD->ymin, DD->ymax );
    printf( "DDsize min etc.: %lg %lg %lg %lg\n", DDsize.xmin, DDsize.xmax, DDsize.ymin, DDsize.ymax );
#endif
#ifdef MYDATAisFLOAT
    printf( "DD min etc.: %g %g %g %g\n", DD->xmin, DD->xmax, DD->ymin, DD->ymax );
    printf( "DDsize min etc.: %g %g %g %g\n", DDsize.xmin, DDsize.xmax, DDsize.ymin, DDsize.ymax );
#endif
#ifdef MYDATAisINT
    printf( "DD min etc.: %i %i %i %i\n", DD->xmin, DD->xmax, DD->ymin, DD->ymax );
    printf( "DDsize min etc.: %i %i %i %i\n", DDsize.xmin, DDsize.xmax, DDsize.ymin, DDsize.ymax );
#endif
#ifdef MYDATAisLONG
    printf( "DD min etc.: %li %li %li %li\n", DD->xmin, DD->xmax, DD->ymin, DD->ymax );
    printf( "DDsize min etc.: %li %li %li %li\n", DDsize.xmin, DDsize.xmax, DDsize.ymin, DDsize.ymax );
#endif
#endif


    return( quit );
}

#undef size_CMM 


/* END_EXTH ----------------------- only private functions follow */

/**************** PrepData ****************/

static void PrepData( MyDataset *DD, MyDatasize *DDsize )
{
    MyDatarecPtr D;
    MyDataPtr    d;
    MyData       min, max;
    int          i, j;
    double       del, idel;

/* find min and max of data recs */

    D = DD->datarec;
    for ( j=0; j<DD->rec_count; j++ )
    {
        d = D->data;
        max = MYDATA_MIN;
        min = MYDATA_MAX;
        for ( i=0; i<DD->data_count; i++ )
        {
            if ( max < *d )
                max = *d;
            if ( min > *d )
                min = *d;
            d++;
        }
#ifdef DEBUG
#ifdef MYDATAisDOUBLE
        printf( "datarec #, min, max: %i %lg %lg\n", j, min, max );
#endif
#ifdef MYDATAisFLOAT
        printf( "datarec #, min, max: %i %g %g\n", j, min, max );
#endif
#ifdef MYDATAisINT
        printf( "datarec #, min, max: %i %i %i\n", j, min, max );
#endif
#ifdef MYDATAisLONG
        printf( "datarec #, min, max: %i %li %li\n", j, min, max );
#endif
#endif
        D->min=min;
        D->max=max;
        D++;
    }

/* set xmin and xmax of data set to min and max of first rec */
/* set ymin and ymax of data set to min and max of other recs */

    D = DD->datarec;
    DD->xmin = D->min;
    DD->xmax = D->max;
    D++;
    DD->ymin = D->min;
    DD->ymax = D->max;
    D++;
    for ( j=2; j<DD->rec_count; j++ )
    {
        if ( DD->ymax < D->max )
            DD->ymax = D->max;
        if ( DD->ymin > D->min )
            DD->ymin = D->min;
        D++;
    }

#ifdef MYDATAisDOUBLE    

/* store the overall data size in DDsize; round the minimum values to below */

	if ( DD->xmin > LONG_MIN+1 )
	{
    	DDsize->xmin = (long)(DD->xmin);
    	if ( DDsize->xmin > DD->xmin )
        	DDsize->xmin -= 1;
    }
    else
    	DDsize->xmin = DD->xmin;
    DDsize->xmax = DD->xmax;
    if ( DD->ymin > LONG_MIN+1 )
    {
    	DDsize->ymin = (long)(DD->ymin);
    	if ( DDsize->ymin > DD->ymin )
        	DDsize->ymin -= 1;
    }
    else
    	DDsize->ymin = DD->ymin;
    DDsize->ymax = DD->ymax;
#ifdef DEBUG
    puts( "in PrepData:" );
    printf( "DDsize min etc.: %lg %lg %lg %lg\n", DDsize->xmin, DDsize->xmax, DDsize->ymin, DDsize->ymax );
#endif
#endif

#ifdef MYDATAisFLOAT    

/* store the overall data size in DDsize; round the minimum values to below */

	if ( DD->xmin > LONG_MIN+1 )
	{
    	DDsize->xmin = (long)(DD->xmin);
    	if ( DDsize->xmin > DD->xmin )
        	DDsize->xmin -= 1;
    }
    else
    	DDsize->xmin = DD->xmin;
    DDsize->xmax = DD->xmax;
    if ( DD->ymin > LONG_MIN+1 )
    {
    	DDsize->ymin = (long)(DD->ymin);
    	if ( DDsize->ymin > DD->ymin )
        	DDsize->ymin -= 1;
    }
    else
    	DDsize->ymin = DD->ymin;
    DDsize->ymax = DD->ymax;
#ifdef DEBUG
    puts( "in PrepData:" );
    printf( "DDsize min etc.: %g %g %g %g\n", DDsize->xmin, DDsize->xmax, DDsize->ymin, DDsize->ymax );
#endif
#endif

#ifdef MYDATAisINT    

/* store the overall data size in DDsize */

    DDsize->xmin = DD->xmin;
    DDsize->xmax = DD->xmax;
    DDsize->ymin = DD->ymin;
    DDsize->ymax = DD->ymax;
#ifdef DEBUG
    puts( "in PrepData:" );
    printf( "DDsize min etc.: %i %i %i %i\n", DDsize->xmin, DDsize->xmax, DDsize->ymin, DDsize->ymax );
#endif
#endif

#ifdef MYDATAisLONG    

/* store the overall data size in DDsize */

    DDsize->xmin = DD->xmin;
    DDsize->xmax = DD->xmax;
    DDsize->ymin = DD->ymin;
    DDsize->ymax = DD->ymax;
#ifdef DEBUG
    puts( "in PrepData:" );
    printf( "DDsize min etc.: %li %li %li %li\n", DDsize->xmin, DDsize->xmax, DDsize->ymin, DDsize->ymax );
#endif
#endif

/* make sure the other values at tic marks are also rounded */

	idel = 0.;
    del = (double)(DDsize->xmax - DDsize->xmin) / ntic;
    if ( del < LONG_MAX-1 )
    {
    	idel = (long)del;
    	if ( idel < del )
        	idel += 1;
    	DDsize->xmax = DDsize->xmin + ntic * idel;
    }
#ifdef DEBUG
    printf( "del, idel: %lg %lg\n", del, idel );
#endif

	idel = 0.;
    del = (double)(DDsize->ymax - DDsize->ymin) / ntic;
    if ( del < LONG_MAX-1 )
	{
    	idel = (long)del;
    	if ( idel < del )
        	idel += 1;
    	DDsize->ymax = DDsize->ymin + ntic * idel;
    }
#ifdef DEBUG
    printf( "del, idel: %lg %lg\n", del, idel );
#endif

}

/**************** PrepPlot ****************/
/*
**  Set DDsize for this x,y plot; cf. coding in PrepData.
**  Assume that min and max of data recs have been set in PrepData.
*/

static void PrepPlot( MyDatarecPtr xdata, MyDatarecPtr ydata, MyDatasize *DDsize )
{
    double      del, idel;

#ifdef MYDATAisDOUBLE    

/* store the data size in DDsize; round the minimum values to below */

	if ( xdata->min > LONG_MIN+1 )
	{
    	DDsize->xmin = (long)(xdata->min);
    	if ( DDsize->xmin > xdata->min )
        	DDsize->xmin -= 1;
    }
    else
    	DDsize->xmin = xdata->min;
    DDsize->xmax = xdata->max;
    if ( ydata->min > LONG_MIN+1 )
    {
    	DDsize->ymin = (long)(ydata->min);
    	if ( DDsize->ymin > ydata->min )
        	DDsize->ymin -= 1;
    }
    else
    	DDsize->ymin = ydata->min;
    DDsize->ymax = ydata->max;
#ifdef DEBUG
    puts( "in PrepPlot:" );
    printf( "DDsize min etc.: %lg %lg %lg %lg\n", DDsize->xmin, DDsize->xmax, DDsize->ymin, DDsize->ymax );
#endif
#endif

#ifdef MYDATAisFLOAT    

/* store the data size in DDsize; round the minimum values to below */

	if ( xdata->min > LONG_MIN+1 )
	{
    	DDsize->xmin = (long)(xdata->min);
    	if ( DDsize->xmin > xdata->min )
        	DDsize->xmin -= 1;
    }
    else
    	DDsize->xmin = xdata->min;
    DDsize->xmax = xdata->max;
    if ( ydata->min > LONG_MIN+1 )
    {
    	DDsize->ymin = (long)(ydata->min);
    	if ( DDsize->ymin > ydata->min )
        	DDsize->ymin -= 1;
    }
    else
    	DDsize->ymin = ydata->min;
    DDsize->ymax = ydata->max;
#ifdef DEBUG
    puts( "in PrepPlot:" );
    printf( "DDsize min etc.: %g %g %g %g\n", DDsize->xmin, DDsize->xmax, DDsize->ymin, DDsize->ymax );
#endif
#endif

#ifdef MYDATAisINT    

/* store the data size in DDsize */

    DDsize->xmin = xdata->min;
    DDsize->xmax = xdata->max;
    DDsize->ymin = ydata->min;
    DDsize->ymax = ydata->max;
#ifdef DEBUG
    puts( "in PrepPlot:" );
    printf( "DDsize min etc.: %i %i %i %i\n", DDsize->xmin, DDsize->xmax, DDsize->ymin, DDsize->ymax );
#endif
#endif

#ifdef MYDATAisLONG    

/* store the data size in DDsize */

    DDsize->xmin = xdata->min;
    DDsize->xmax = xdata->max;
    DDsize->ymin = ydata->min;
    DDsize->ymax = ydata->max;
#ifdef DEBUG
    puts( "in PrepPlot:" );
    printf( "DDsize min etc.: %li %li %li %li\n", DDsize->xmin, DDsize->xmax, DDsize->ymin, DDsize->ymax );
#endif
#endif

/* make sure the other values at tic marks are also rounded */

	idel = 0.;
    del = (double)(DDsize->xmax - DDsize->xmin) / ntic;
    if ( del < LONG_MAX-1 )
    {
    	idel = (long)del;
    	if ( idel < del )
        	idel += 1;
    	DDsize->xmax = DDsize->xmin + ntic * idel;
    }
#ifdef DEBUG
    printf( "del, idel: %lg %lg\n", del, idel );
#endif

	idel = 0.;
    del = (double)(DDsize->ymax - DDsize->ymin) / ntic;
    if ( del < LONG_MAX-1 )
	{
    	idel = (long)del;
    	if ( idel < del )
        	idel += 1;
    	DDsize->ymax = DDsize->ymin + ntic * idel;
    }
#ifdef DEBUG
    printf( "del, idel: %lg %lg\n", del, idel );
#endif

}

/**************** PrepPage ****************/

#define    size_STRING  80

static void PrepPage( Rect *canvas, int nx, int ny, int *dx, int *dy, 
                      int *xsz, int *ysz, MyDataset *DD, MyDatasize *DDsize )
{
    char    str[size_STRING];
    int     len, tmp;


/* make the format strings for printing the values */
/* adjust ylab accordingly */

    len = sprintf( str, PREP_FMT, DDsize->xmin );
    tmp = sprintf( str, PREP_FMT, DDsize->xmax );
    if ( tmp > len )
        len = tmp;
    sprintf( xfmt, XFMT, len+XADDLEN );
    len = sprintf( str, PREP_FMT, DDsize->ymin );
    tmp = sprintf( str, PREP_FMT, DDsize->ymax );
    if ( tmp > len )
        len = tmp;
    sprintf( yfmt, YFMT, len+YADDLEN );

    ylab = (len+YADDLEN) * kFontWidth;

#ifdef DEBUG
    printf( "%s %s\n", xfmt, yfmt );
#endif


/* 
**  size in x-direction: nx * (xsz+ylab) + (nx-1) * xspacing
**  size in y-direction: ny * (ysz+xlab) + (ny-1) * yspacing
**   
**  let: xspacing = spc * (xsz+ylab)
**  let: yspacing = spc * (ysz+xlab)
**  
**  then: 
**  size in x-direction: (xsz+ylab) * (nx + (nx-1) * spc)
**  size in y-direction: (ysz+xlab) * (ny + (ny-1) * spc)
*/

/* calculate the plot sizes as explained above */

    *xsz = (canvas->right - canvas->left) / (nx + (nx-1) * spc) - ylab;
    *ysz = (canvas->bottom - canvas->top) / (ny + (ny-1) * spc) - xlab;
    
    *dx = (1 + spc) * (*xsz + ylab);
    *dy = (1 + spc) * (*ysz + xlab);
}

#undef    size_STRING


#ifdef UNIX_CC

/**************** GraphPageInit ****************/

static void  GraphPageInit( char *text )
{
    window = NEW( Window, 1 );
    window->portRect.top    = 0;
    window->portRect.left   = 0;
    window->portRect.bottom = 300;
    window->portRect.right  = 500;
}

/**************** GraphPageEnd ****************/

static void  GraphPageEnd( void )
{
    free( window );
}

#endif
